Jump to content

GStreamer Performance Review for the Dragonwing EVK Board

From RidgeRun Developer Wiki


Follow us on: YouTube Twitter LinkedIn Email Share this page

Share This Page





Problems running the pipelines shown on this page? Please see our GStreamer Debugging guide for help .


This section establishes the methodology used for the performance measurements. If you are looking for the performance results for different scenarios, visit the following pages:

RidgeRun evaluates GStreamer pipelines performance on the Qualcomm Dragonwing IQ-9075 EVK with three complementary measurements: per-element latency, sustained resource behavior, and maximum pipeline throughput. The methodology presented in this page tracks latency, CPU and GPU utilization, memory, and FPS so developers can compare software and hardware-accelerated paths under documented conditions. Results are specific to the pipeline topology, software image, GStreamer/plugin versions, clocking, memory transfers, and test setup. To find the results for specific cases, visit the links below.


How We Measure Performance

The performance analysis was done using three different benchmarks: element latency, average behavior and limit performance of each pipeline.

Element Latency

Element latency was measured with RidgeRun's script tool in the Pipeline Latency section for RidgeRun's Developer Manual. This script parses and summarizes latency measurements obtained from a GStreamer pipeline and gives a detailed table with statistics such as average latency, min/max latency, and percentiles to quantify latency.

Resource Usage Average Behavior

The average behavior of each pipeline was measured by reading CPU and GPU utilization with the following commands during realistic testing cases for each pipeline, using the example pipelines mentioned for each element tested:

watch ps -o pid,cmd,%mem,rss -C gst-launch-1.0
watch -n 1 cat /sys/class/kgsl/kgsl-3d0/gpubusy

These commands display the raw and relative memory usage, and the raw and relative usage of the GPU. Also, the RidgeRun team developed a GStreamer element named perf utilized to measure CPU performance and FPS output. You can find more information on how to install it and usage on GstPerf.

Limit Performance

Limit performance can be measured by stressing the FPS output to the max while avoiding unnecessary overhead to the pipeline and any bottleneck that coming from elements outside the testing scope. This is why pipelines are structured in this way: source, element under test and a fakesink, similar to the next pipeline:

gst-launch-1.0 videotestsrc num-buffers=1 pattern=ball ! "video/x-raw,format=${FORMAT},height=${HEIGHT},width=${WIDTH}" ! imagefreeze ! queue ! testelement ! queue ! perf print-cpu-load=true ! fakesink

This pipeline structure removes any overhead added by unrelated elements and allows the tested element to operate at its performance limit. As you can see, the perf element is also added with the print-cpu-load=true to verify CPU usage and max FPS produced.

copy element

The addition of the copy elements was necessary in the limit performance measurement for the transformation elements in the Video Transformation section. This is due how the imagefreeze interacts with the transformation elements and the EGL textures package. You can find the source code and necessary commands for installation here:

Find the copy element source code here

#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
#include <gst/video/video.h>


G_BEGIN_DECLS

#define GST_TYPE_COPY (gst_copy_get_type())
G_DECLARE_FINAL_TYPE(GstCopy, gst_copy, GST, COPY, GstBaseTransform)

G_END_DECLS


GST_DEBUG_CATEGORY_STATIC (gst_copy_debug_category);

#define GST_CAT_DEFAULT gst_copy_debug_category

struct _GstCopy
{
  GstBaseTransform base_copy;
};


static GstFlowReturn gst_copy_transform_frame (GstBaseTransform * filter,
    GstBuffer *, GstBuffer *);
static gboolean gst_copy_start (GstBaseTransform * trans);

enum
{
  PROP_0,
};

#define GST_BAYER_CAPS_MAKE(format) \
  "video/x-bayer,"                  \
  "format=" format                  \
  ","                               \
  "width=" GST_VIDEO_SIZE_RANGE     \
  ","                               \
  "height=" GST_VIDEO_SIZE_RANGE    \
  ","                               \
  "framerate=" GST_VIDEO_FPS_RANGE

#define VIDEO_SRC_CAPS GST_VIDEO_CAPS_MAKE(GST_VIDEO_FORMATS_ALL)
//    GST_BAYER_CAPS_MAKE("{ rggb, bggr, gbrg, grbg }")

#define VIDEO_SINK_CAPS GST_VIDEO_CAPS_MAKE(GST_VIDEO_FORMATS_ALL)
//   GST_BAYER_CAPS_MAKE("{ rggb, bggr, gbrg, grbg }")

G_DEFINE_TYPE_WITH_CODE (GstCopy, gst_copy, GST_TYPE_BASE_TRANSFORM,
    GST_DEBUG_CATEGORY_INIT (gst_copy_debug_category, "copy", 0,
        "debug category for copy element"));


static void
gst_copy_class_init (GstCopyClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstBaseTransformClass *base_transform_class =
      GST_BASE_TRANSFORM_CLASS (klass);

  /* Setting up pads and setting metadata should be moved to
     base_class_init if you intend to subclass this class. */
  gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
      gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
          gst_caps_from_string (VIDEO_SRC_CAPS)));
  gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
      gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
          gst_caps_from_string (VIDEO_SINK_CAPS)));

  gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
      "Copy element", "Generic",
      "Copy element over a video stream",
      "Luis G. Leon-Vega <luis.leon@ridgerun.com>");

  base_transform_class->transform =
      GST_DEBUG_FUNCPTR (gst_copy_transform_frame);
  base_transform_class->start = GST_DEBUG_FUNCPTR (gst_copy_start);
}

static void
gst_copy_init (GstCopy * self)
{
}

static gboolean
gst_copy_start (GstBaseTransform * trans)
{
  gst_base_transform_set_in_place (trans, FALSE);
  return TRUE;
}

static GstFlowReturn
gst_copy_transform_frame (GstBaseTransform * filter,
    GstBuffer * inframe, GstBuffer * outframe)
{
  GstMapInfo inmap;
  GstMapInfo outmap;

  gst_buffer_map (inframe, &inmap, GST_MAP_READ);
  gst_buffer_map (outframe, &outmap, GST_MAP_WRITE);

  memcpy(outmap.data, inmap.data, inmap.size);

  gst_buffer_unmap (outframe, &outmap);
  gst_buffer_unmap (inframe, &inmap);

  return GST_FLOW_OK;
}

static gboolean
plugin_init (GstPlugin * plugin)
{
  if (gst_element_register (plugin, "copy", GST_RANK_PRIMARY,
          GST_TYPE_COPY) == FALSE) {
    return FALSE;
  }

  return TRUE;
}

#ifndef PACKAGE
#define PACKAGE "copy"
#endif


GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    copy,
    "Image processing library plugin",
    plugin_init, "0.1.0", "Proprietary", "RidgeRun", "https://www.ridgerun.com")


  • Install the copy element:
gcc -fPIC -c gstcopy.c -o gstcopy.o `pkg-config gstreamer-base-1.0 gstreamer-1.0 --cflags` && gcc -shared gstcopy.o -o libgstcopy.so `pkg-config gstreamer-1.0 gstreamer-video-1.0 --libs`

sudo cp libgstcopy.so /usr/lib/aarch64-linux-gnu/gstreamer-1.0/

FAQ

How is GStreamer performance measured on the Qualcomm Dragonwing IQ-9075 EVK?
RidgeRun combines per-element latency, sustained CPU/GPU/memory/FPS measurements, and maximum-throughput tests. The three views help separate processing delay, resource cost, and pipeline throughput.
What is the difference between element latency and glass-to-glass latency?
Element latency measures processing associated with a pipeline stage, while glass-to-glass latency includes the complete path from image capture through processing to visible display output.
Why use fakesink for maximum-throughput tests?
A fakesink removes display or storage work that could otherwise become the bottleneck, helping isolate the element under test. The result is a synthetic throughput limit, not a complete application-latency measurement.
Which GStreamer version is used on this Dragonwing IQ-9075 guide?
The GStreamer version 1.24.2 included with the Ubuntu 24.04 setup.



Cookies help us deliver our services. By using our services, you agree to our use of cookies.